class Show {
    constructor(opts) {
        const { el, data, methods } = opts;
        this.el = document.querySelector(el);
        this.data = data;
        this.methods = methods;
        this.domPool = new Map();
        this.eventPool = new Map();

        this.init();
    }

    //项目初始化
    init() {
        this.initData();
        this.initDom(this.el);
        this.initView(this.domPool);
        this.initEvent(this.eventPool);

        console.log(this.domPool);
        console.log(this.eventPool);
    }

    //数据初始化，达成可以使用this来访问this.data，加上一层代理
    initData() {
        for (let key in this.data) {
            Object.defineProperty(this, key, {
                get() {
                    console.log('获取' + key + this.data[key]);
                    return this.data[key];
                },
                set(newValue) {
                    this.data[key] = newValue;
                    this.domChange(key, this.domPool);
                }
            })
        }
        console.log(this)
    }

    //初始化dom节点，把dom元素，和需要的数据关联，并放在一个可以迭代的容器中，方便后面的遍历，这里选择使用new Map()
    initDom(el) {
        var _childNodes = el.childNodes;
        _childNodes.forEach(item => {
            if (item.nodeType === 1) {
                const vIf = item.getAttribute('v-if');
                const vShow = item.getAttribute('v-show');
                const vEvent = item.getAttribute('@click');
                if (vIf) {
                    this.domPool.set(item, {
                        type: 'if',
                        show: this.data[vIf],
                        data: vIf
                    })
                } else if (vShow) {
                    this.domPool.set(item, {
                        type: 'show',
                        show: this.data[vShow],
                        data: vShow
                    })
                }

                if (vEvent) {
                    this.eventPool.set(item, this.methods[vEvent])
                }
            }
            this.initDom(item);
        });
    }

    //初始化视图，初始的时候，不需要传递参数，只需要按照之前保存的状态渲染出来就可以
    initView(domPool) {
        this.domChange(null, domPool);
    }

    //改变视图函数
    domChange(data, domPool) {

        //初始化
        /**
         * 如果没有传递data，说明是初始状态
         * 遍历状态数据
         * 判断是if还是show
         * 如果是if，根据v-if的本质，是直接在document中删除dom元素，但是我们之后有可能还需要让他显示，所以我们要保存一下dom，并且创造一个元素来记录它本身的位置
         * 如果是show，根据v-show的本质，我们直接改变元素的display属性就可以了
         */
        if (!data) {
            for (let [k, v] of domPool) {
                switch (v.type) {
                    case 'if':
                        v.comment = document.createComment('v-if');
                        !v.show && k.parentNode.replaceChild(v.comment, k)
                        break;
                    case 'show':
                        !v.show && (k.style.display = 'none')
                        break;
                    default:
                        break;
                }
            }
            return;
        }

        //
        for (let [k, v] of domPool) {

            /**
             * v.data是我们存储状态时候的v-if='v.data'的值
             * data是我们传递过来的data里面的键名
             * 
             * 在我们点击不同的按钮的时候，传递过来的data是不一样的，只有data与dom元素的v-if或者v-show绑定的数据一样时，我们才能进行操作
             */
            if (v.data === data) {
                switch (v.type) {
                    case 'if':

                        /**
                         * 这里要注意，我们在删除了元素本身的时候，我们放了一个占位元素进去，所以在下一次的时候，我们就需要从占位元素来获取parentNode
                         */
                        v.show ? k.parentNode.replaceChild(v.comment, k) :
                            v.comment.parentNode.replaceChild(k, v.comment);
                        v.show = !v.show;
                        break;
                    case 'show':
                        v.show ? k.style.display = 'none' :
                            k.style.display = 'block';
                        break;
                    default:
                        break;
                }
            }
        }
    }

    //初始化事件绑定
    initEvent(eventPool) {
        for (let [k, v] of eventPool) {
            k.addEventListener('click', v.bind(this), false)
        }
    }
}